package com.hotec.PROJECT_NAME.component.dtohandler.callbackhandler;

import com.gemcap.framework.common.data.dto.support.DTOCallbackHandler;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hotec.PROJECT_NAME.modules.sys.service.SysDictService;
import lombok.Data;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 对待转换的实体进行字典项的转换
 */
@Data
public class DTOCallbackHandlerWithDic implements DTOCallbackHandler {

    private Map<String, String> propertyDicMap = Maps.newHashMap();

    private Map<String, Map<String, String>> dictionaryMap;

    private SysDictService sysDictService;

    /**
     * 转换后字典项的后缀
     */
    private String propertyDicPostfix = "_dic";

    /**
     * 默认5分钟更新一次字典项
     */
    private QueryTimer queryTimer = new QueryTimer(20);


    /**
     * 查询字典项
     */
    public synchronized void initDictionaryMap() {
        //如果字典值为空 或 已经超时 ， 则更新字典项
        if (dictionaryMap == null || queryTimer.isTimeout()) {

            //获取需要查询的父字典项code
            List<String> parentCodes = Lists.newArrayList(propertyDicMap.values());
            if (parentCodes == null || parentCodes.size() < 1) {
                return;
            }

            dictionaryMap = Maps.newHashMap();

            for (String parentCode : parentCodes) {
                dictionaryMap.put(parentCode, sysDictService.queryChildrenMap(parentCode));
            }
        }
    }

    /**
     * 是否为备选的字典项值
     *
     * @return
     */
    public boolean isAvailableDicValue(Object value) {
        //如果值不是字符串、不是基本数据类型，则不能作为字典项的code进行匹配查询
        if (value != null && ((value instanceof String) || ClassUtils.isPrimitiveOrWrapper(value.getClass()))) {
            return true;
        }

        return false;
    }

    /**
     * 返回父节点code下的所有子节点信息
     *
     * @param code
     * @return
     */
    public Map<String, String> getDictionaryItemMap(String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        return dictionaryMap.get(code);
    }

    /**
     * 进行字典项转换的处理
     *
     * @param dtoMap
     */
    @Override
    public void doHandler(Map<String, Object> dtoMap) {
        initDictionaryMap();

        if (dtoMap == null || dictionaryMap == null) {
            return;
        }

        //临时存储转换后的字典项
        Map<String, String> dicDto = Maps.newHashMap();

        for (Map.Entry<String, Object> item : dtoMap.entrySet()) {
            //判断是否可以使用字典项
            if (item.getKey() == null || !isAvailableDicValue(item.getValue()) ||
                    StringUtils.isBlank(propertyDicMap.get(item.getKey()))) {
                continue;
            }

            //获取字典项map
            Map<String, String> dicItemMap = getDictionaryItemMap(propertyDicMap.get(item.getKey()));

            String dicCode = item.getValue().toString();
            //添加字典项的值，如果没有则字典项的值默认为空
            if (dicItemMap != null && StringUtils.isNotBlank(dicCode)) {
                String dicValue = "";
                //如果字典值有多个，则使用逗号进行分割，构建字典值时也是用逗号连接
                if (dicCode.indexOf(",") != -1) {
                    List<String> codes = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(dicCode);
                    for (String code : codes) {
                        if (dicItemMap.get(code) == null) {
                            continue;
                        }
                        if (dicValue.length() > 0) {
                            dicValue += ",";
                        }
                        dicValue += dicItemMap.get(code);
                    }
                }
                //如果使用逗号找不到对应的字典值 或 没有逗号，则直接获取字典值
                if (StringUtils.isBlank(dicValue)) {
                    dicValue = dicItemMap.get(dicCode);
                }

                dicDto.put(item.getKey() + getPropertyDicPostfix(), dicValue);
            } else {
                dicDto.put(item.getKey() + getPropertyDicPostfix(), null);
            }
        }

        dtoMap.putAll(dicDto);

    }

    /**
     * 查询出超时判断
     */
    class QueryTimer {
        private Date lastTime;

        private long timeout;

        /**
         * 初始化超时时间，单位为秒
         *
         * @param timeout
         */
        public QueryTimer(long timeout) {
            this.timeout = timeout;
        }

        /**
         * 判断是否已经超时
         *
         * @return
         */
        public boolean isTimeout() {
            if (lastTime == null) {
                lastTime = new Date();
                return false;
            }

            Date currentTime = new Date();

            //判断是否已经超时
            boolean flag = ((currentTime.getTime() - lastTime.getTime()) / 1000 - timeout) > 0;
            if (flag) {
                lastTime = currentTime;
            }

            return flag;
        }
    }
}
